package com.exwave.socialgame.model_wolfgame.controller;

import com.exwave.socialgame.jwt_token.Token;
import com.exwave.socialgame.model_wolfgame.wolfdata.Event;
import com.exwave.socialgame.model_wolfgame.wolfdata.Room;
import com.exwave.socialgame.model_wolfgame.service.RoomsService;
import com.exwave.socialgame.myutils.ReturnUtils;
import com.exwave.socialgame.myutils.WolfGameUtils;
import com.exwave.socialgame.myutils.ParamsException;
import com.exwave.socialgame.myutils.RedisForWolfUtils;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.annotations.ApiIgnore;

@RestController
@RequestMapping("gameop")
public class GameController {
    @Resource
    private RoomsService roomsService;

    @Resource
    private RedisForWolfUtils redisForWolfUtils;


    private Event countUserStatus(Event event, Room room) {
        if (event.getOp() == 1005) { //收到狼人操作结束，获取操作结果
            Event event1 = redisForWolfUtils.readEvent(room.getKey_Room(), room.getData(), room.getStage(), 11);
            //统计被杀的玩家
            HashMap<Integer, Integer> hashMap = new HashMap<>();
            for (Integer j : event1.getDest()) {
                if (hashMap.containsKey(j))
                    hashMap.put(j, hashMap.get(j) + 1);
                else
                    hashMap.put(j, 1);
            } //统计完成，获取票数最多的玩家
            int key, maxkey = 0;
            int value, maxvalue = 0;
            Set<Map.Entry<Integer, Integer>> entries = hashMap.entrySet();
            for (Map.Entry<Integer, Integer> entry : entries) {
                //key value 代表每轮遍历出来的值
                key = entry.getKey();
                value = entry.getValue();
                if (maxvalue < value) {
                    //maxKey maxValue 当判断出最大值是将最大值赋予该变量
                    maxkey = key;
                    maxvalue = value;
                }
            }
            List<Integer> list = new ArrayList<>();
            list.add(maxkey);
            try {
                room.getUsers().get(maxkey - 1).getRole().setState(0); //玩家状态改为死亡
                return new Event(event.getSource(), 11, list);
            } catch (Exception e) {
                throw new ParamsException(e.getMessage());
            }
        } else if (event.getOp() == 1) {
            //女巫毒人，默认已经知道玩家生存状态
            int dest = event.getDest().get(0);
            int status = room.getUsers().get(dest - 1).getRole().getState();
            if (status == 1) {
                try {
                    room.getUsers().get(dest - 1).getRole().setState(0); //玩家状态改为死亡
                    return event;
                } catch (Exception e) {
                    throw new ParamsException(e.getMessage());
                }
            } else
                throw new ParamsException("玩家已阵亡，请勿重复用毒");
        } else if (event.getOp() == 2) {
            int dest = event.getDest().get(0);
            int status = room.getUsers().get(dest - 1).getRole().getState();
            if (status != 1) {
                try {
                    room.getUsers().get(dest - 1).getRole().setState(1); //玩家状态改为复活
                    return event;
                } catch (Exception e) {
                    throw new ParamsException(e.getMessage());
                }
            } else
                throw new ParamsException("玩家不需要用药");
        }
        return null; //没有人变化
    }


    /**
     * 记录玩家提交的操作
     * 房间号 + 记录类型 + 夜晚数 == 操作唯一标识
     * Version 1.5 记录事件每次添加到房间中，方便查询
     *
     * @param roomId ID Of Room
     * @return Object
     */
    @PostMapping("addEvent")
    @Token.UserLoginToken
    @ApiOperation(value = "事件提交")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roomId", value = "ID Of Room", required = true, dataTypeClass = Integer.class, paramType = "query"),
            @ApiImplicitParam(name = "token", value = "Token", required = true, dataTypeClass = String.class, paramType = "header")
    })
    public Object addEvent(@RequestBody Event event, Integer roomId) {
        Room room = redisForWolfUtils.readRoom(roomId);        //获取房间
        Event event1;
        HashMap<String, Object> map = new HashMap<>();
        try {
            if (room.getTimes() <= 0 || room.getData() <= 0) {
                throw new ParamsException("请先开始游戏");
            }
            // 优先进行逻辑操作判断
            event1 = countUserStatus(event, room);
            room.addEvent(event);
            redisForWolfUtils.saveRoom(room);
            if (event1 != null) { //有人员变化
                map.put("event", event1);
                return WolfGameUtils.returnSuccess(201, map);
            }
            //然后将事件存入房间中
            Event eventTmp = redisForWolfUtils.readEvent(roomId, room.getData(), room.getStage(), event.getOp());
            //如果有类似的操作，则获取出来
            if (eventTmp != null) {
                //有这样的操作，将发起人加入，房间号，天数，操作，唯一Event
                eventTmp.addSource(event.getSource().get(0));
                eventTmp.addDest(event.getDest().get(0)); //将每个人的Event都存入，同种操作类型
                redisForWolfUtils.saveEvent(roomId, room.getData(), room.getStage(), event.getOp(), eventTmp); //存入当天的Event
            } else {
                //没有类似操作，首先存入一个
                redisForWolfUtils.saveEvent(roomId, room.getData(), room.getStage(), event.getOp(), event);
            }
            //Event存入以后，现在加入房间中
            room.addEvent(eventTmp);
        } catch (ParamsException p) {
            return WolfGameUtils.returnFailure(p.getCode(), p.getMsg());
        } catch (Exception e) {
            return WolfGameUtils.returnFailure(e.getMessage());
        }
        return WolfGameUtils.returnSuccess(null);
    }

    /**
     * 天黑
     *
     * @param roomId ID Of Room
     * @return Object
     */
    @Token.UserLoginToken
    @PostMapping("toNight")
    @ApiOperation(value = "天黑了")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roomId", value = "房间ID", required = true, dataTypeClass = Integer.class, paramType = "query"),
            @ApiImplicitParam(name = "token", value = "Token", required = true, dataTypeClass = String.class, paramType = "header")
    })
    public Object toNight(int roomId) {
        Room room;
        if (redisForWolfUtils.isNotNull("R", roomId)) { //房间存在
            room = redisForWolfUtils.readRoom(roomId); //获取房间
            room.toTomorrow(); //天数加一，因为初始化天数为0；
            //删除前一天白天的事件
            room.delCurrentEvents(redisForWolfUtils);
            room.toNight(); //白天事件添加完成后，将房间状态设置为夜晚
            redisForWolfUtils.saveRoom(room);
            return WolfGameUtils.returnSuccess(null);
        } else
            return WolfGameUtils.returnFailure("room haven't been created");
    }

    /**
     * 房间号 进入白天
     *
     * @param roomId ID Of Room
     * @return Object
     */
    @Token.UserLoginToken
    @PostMapping("toDayNight")
    @ApiOperation(value = "天亮了")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roomId", value = "房间ID", required = true, dataTypeClass = Integer.class, paramType = "query"),
            @ApiImplicitParam(name = "token", value = "Token", required = true, dataTypeClass = String.class, paramType = "header")
    })
    public Object toDayNight(int roomId) {
        Room room;
        if (redisForWolfUtils.isNotNull("R", roomId)) { //房间存在
            room = redisForWolfUtils.readRoom(roomId); //获取房间
            //因为是白天，所以天数不加一
            //删除当天夜晚的事件
            room.delCurrentEvents(redisForWolfUtils);
            room.toDayNight(); //进入白天
            redisForWolfUtils.saveRoom(room);
            return WolfGameUtils.returnSuccess(null);
        } else
            return WolfGameUtils.returnFailure("room haven't been created");
    }


    /**
     * 位置分配角色（发牌）
     * 即开始游戏
     *
     * @param locateRole 分配的角色
     * @return success
     */
    @Token.UserLoginToken
    @ApiOperation(value = "分配角色/开始游戏")
    @PostMapping("assignRoles")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roomId", value = "房间ID", required = true, dataTypeClass = Integer.class, paramType = "query"),
            @ApiImplicitParam(name = "token", value = "Token", required = true, dataTypeClass = String.class, paramType = "header")
    })
    public Object assignRoles(@RequestBody List<Integer> locateRole, int roomId) {
        Room room;
        if (redisForWolfUtils.isNotNull("R", roomId)) { //房间存在
            room = redisForWolfUtils.readRoom(roomId); //获取房间
            /*将结果保存入上一局，并初始化新的一局*/
            room.delCurrentEvents(redisForWolfUtils);
            room.setStage(0); //恢复为白天
            room.setData(0); //恢复第一天
            room.setLocate_role(locateRole); //设置发牌数据
            room.toNextGame(); //开始游戏
            redisForWolfUtils.saveRoom(room);
            return WolfGameUtils.returnSuccess(null);
        }
        return WolfGameUtils.returnFailure("room haven't been created");
    }

    /**
     * 开启投票
     *
     * @param roomId 房间号
     */
    @Token.UserLoginToken
    @PostMapping("onVote")
    @ApiOperation(value = "开启投票")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "Token", required = true, dataTypeClass = String.class, paramType = "header"),
            @ApiImplicitParam(name = "roomId", value = "房间号ID", required = true, dataTypeClass = Integer.class, paramType = "query")
    })
    public Object onVote(int roomId) {
        if (!redisForWolfUtils.isNotNull("R", roomId))
            return WolfGameUtils.returnFailure("房间不存在");
        Room room = redisForWolfUtils.readRoom(roomId);
        redisForWolfUtils.onVote(roomId);
        return WolfGameUtils.returnSuccess();
    }

    /**
     * 关闭投票
     *
     * @param roomId 房间号
     */
    @Token.UserLoginToken
    @PostMapping("offVote")
    @ApiOperation(value = "结束投票")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "Token", required = true, dataTypeClass = String.class, paramType = "header"),
            @ApiImplicitParam(name = "roomId", value = "房间号ID", required = true, dataTypeClass = Integer.class, paramType = "query")
    })
    public Object offVote(int roomId) {
        if (!redisForWolfUtils.isNotNull("R", roomId))
            return WolfGameUtils.returnFailure("房间不存在");
        Room room = redisForWolfUtils.readRoom(roomId);
        redisForWolfUtils.offVote(roomId);
        //选出幸运儿
        Event event = redisForWolfUtils.readEvent(roomId, room.getData(), room.getStage(), 1003);
//        HashMap<Integer, Integer> hashMap = new HashMap<>();
//        for (Integer j : event.getDest()) {
//            if (hashMap.containsKey(j))
//                hashMap.put(j, hashMap.get(j) + 1);
//            else
//                hashMap.put(j, 1);
//        } //统计完成，获取票数最多的玩家
//        int key = 0, maxkey = 0;
//        int value = 0, maxvalue = 0;
//        Set<Map.Entry<Integer, Integer>> entries = hashMap.entrySet();
//        for (Map.Entry<Integer, Integer> entry : entries) {
//            //key value 代表每轮遍历出来的值
//            key = entry.getKey();
//            value = entry.getValue();
//            if (maxvalue < value) {
//                //maxKey maxValue 当判断出最大值是将最大值赋予该变量
//                maxkey = key;
//                maxvalue = value;
//            }
//        }
////        if (value == event.getSource().size() / 2)
////            throw new ParamsException("票数打平，请重新投票");
//        HashMap<String, Object> map = new HashMap<>();
//        List<Integer> list = new ArrayList<>();
//        list.add(maxkey);
//        try {
//            room.getUsers().get(maxkey - 1).getRole().setState(0); //玩家状态改为死亡
//            Event event1 = new Event(event.getSource(), 1003, list);
//            map.put("event", event1);
//        } catch (Exception e) {
//            return MyReUtil.returnFailure(e.getMessage());
//        }
        if (event != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("event", event);
            return WolfGameUtils.returnSuccess(201, map);
        } else
            return WolfGameUtils.returnFailure("投票失败");
    }


    /**
     * 公布结果
     *
     * @param roomId 房间号
     * @return event 事件
     */
    @ApiIgnore
    @Token.UserLoginToken
    @PostMapping("anoResult")
    @ApiOperation(value = "公布结果")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roomId", value = "房间ID", required = true, dataTypeClass = Integer.class, paramType = "query"),
            @ApiImplicitParam(name = "token", value = "Token", required = true, dataTypeClass = String.class, paramType = "header")
    })
    public Object anoResult(int roomId) {
        HashMap<String, Object> map = new HashMap<>();
        if (!redisForWolfUtils.isNotNull("R", roomId))
            return ReturnUtils.returnMap(500, "unknown error"); //没有找到房间
        Room room = redisForWolfUtils.readRoom(roomId);
        /*对eventList进行处理*/



        /*判断有无人员阵亡*/
        return ReturnUtils.returnMap(200, "暂定返回list，还没进行判断，判断后返回一个Event", map);
    }
}
